use rand::prelude::SliceRandom;
use zxcvbn::zxcvbn;
use crate::opts::GenPassOpts;

const UPPER: &[u8] = b"QWERTYUIOPASDFGHJKLZXCVBNM";
const LOWER: &[u8] = b"qwertyuiopasdfghjklzxcvbnm";
const NUMBER: &[u8] = b"0123456789";
const SYMBOL: &[u8] = b"!@#$%^&*_";

pub fn gen_pass_word(lowercase: bool, uppercase: bool, number: bool, symbol: bool, length: u8) -> anyhow::Result<String> {
    let mut rng = rand::thread_rng();

    let mut passwd = Vec::new();

    let mut chars = Vec::new();

    // 保证每种字符类型都有
    if lowercase {
        chars.extend_from_slice(LOWER);

        passwd.push(*LOWER.choose(&mut rng).expect(""))
    }

    if uppercase {
        chars.extend_from_slice(UPPER);
        passwd.push(*UPPER.choose(&mut rng).expect(""))
    }

    if number {
        chars.extend_from_slice(NUMBER);
        passwd.push(*NUMBER.choose(&mut rng).expect(""))
    }

    if symbol {
        chars.extend_from_slice(SYMBOL);
        passwd.push(*SYMBOL.choose(&mut rng).expect(""))
    }

    let c = chars.choose(&mut rng).unwrap();
    passwd.push(*c);

    for _ in 0..(length - passwd.len() as u8) {
        // 从 chars 中随机选一个
        let c = chars.choose(&mut rng).unwrap();
        passwd.push(*c);
    }

    // 再把顺序打乱
    passwd.shuffle(&mut rng);

    let passwd = String::from_utf8(passwd)?;

    // 检查密码强度
    let res = zxcvbn(&passwd, &[]);

    eprintln!("passwd 强度: {:?}", res.score());
    Ok(passwd)
}


#[test]
fn testpass() {
    let opt = GenPassOpts {
        length: 16,

        uppercase: true,

        lowercase: true,

        number: true,

        symbol: true,

    };
    let res = gen_pass_word(opt.lowercase, opt.uppercase, opt.number, opt.symbol, opt.length);

    println!("res is {}", res.unwrap());
}